home *** CD-ROM | disk | FTP | other *** search
/ Personal Computer World 2008 February / PCWFEB08.iso / Software / Freeware / Miro 1.0 / Miro_Installer.exe / xulrunner / python / BitTorrent / Encrypter.py < prev    next >
Encoding:
Python Source  |  2007-11-12  |  18.3 KB  |  640 lines

  1. # Written by Bram Cohen
  2. # see LICENSE.txt for license information
  3.  
  4. from cStringIO import StringIO
  5. from binascii import b2a_hex
  6. from socket import error as socketerror
  7.  
  8. protocol_name = 'BitTorrent protocol'
  9.  
  10. def toint(s):
  11.     return long(b2a_hex(s), 16)
  12.  
  13. def tobinary(i):
  14.     return (chr(i >> 24) + chr((i >> 16) & 0xFF) + 
  15.         chr((i >> 8) & 0xFF) + chr(i & 0xFF))
  16.  
  17. # header, reserved, download id, my id, [length, message]
  18.  
  19. class Connection:
  20.     def __init__(self, Encoder, connection, id, is_local):
  21.         self.encoder = Encoder
  22.         self.connection = connection
  23.         self.id = id
  24.         self.locally_initiated = is_local
  25.         self.complete = False
  26.         self.closed = False
  27.         self.buffer = StringIO()
  28.         self.next_len = 1
  29.         self.next_func = self.read_header_len
  30.         if self.locally_initiated:
  31.             connection.write(chr(len(protocol_name)) + protocol_name + 
  32.                 (chr(0) * 8) + self.encoder.download_id)
  33.             if self.id is not None:
  34.                 connection.write(self.encoder.my_id)
  35.  
  36.     def get_ip(self):
  37.         return self.connection.get_ip()
  38.  
  39.     def get_id(self):
  40.         return self.id
  41.  
  42.     def is_locally_initiated(self):
  43.         return self.locally_initiated
  44.  
  45.     def is_flushed(self):
  46.         return self.connection.is_flushed()
  47.  
  48.     def read_header_len(self, s):
  49.         if ord(s) != len(protocol_name):
  50.             return None
  51.         return len(protocol_name), self.read_header
  52.  
  53.     def read_header(self, s):
  54.         if s != protocol_name:
  55.             return None
  56.         return 8, self.read_reserved
  57.  
  58.     def read_reserved(self, s):
  59.         return 20, self.read_download_id
  60.  
  61.     def read_download_id(self, s):
  62.         if s != self.encoder.download_id:
  63.             return None
  64.         if not self.locally_initiated:
  65.             self.connection.write(chr(len(protocol_name)) + protocol_name + 
  66.                 (chr(0) * 8) + self.encoder.download_id + self.encoder.my_id)
  67.         return 20, self.read_peer_id
  68.  
  69.     def read_peer_id(self, s):
  70.         if not self.id:
  71.             if s == self.encoder.my_id:
  72.                 return None
  73.             for v in self.encoder.connections.values():
  74.                 if s and v.id == s:
  75.                     return None
  76.             self.id = s
  77.             if self.locally_initiated:
  78.                 self.connection.write(self.encoder.my_id)
  79.             else:
  80.                 self.encoder.everinc = True
  81.         else:
  82.             if s != self.id:
  83.                 return None
  84.         self.complete = True
  85.         self.encoder.connecter.connection_made(self)
  86.         return 4, self.read_len
  87.  
  88.     def read_len(self, s):
  89.         l = toint(s)
  90.         if l > self.encoder.max_len:
  91.             return None
  92.         return l, self.read_message
  93.  
  94.     def read_message(self, s):
  95.         if s != '':
  96.             self.encoder.connecter.got_message(self, s)
  97.         return 4, self.read_len
  98.  
  99.     def read_dead(self, s):
  100.         return None
  101.  
  102.     def close(self):
  103.         if not self.closed:
  104.             self.connection.close()
  105.             self.sever()
  106.  
  107.     def sever(self):
  108.         self.closed = True
  109.         del self.encoder.connections[self.connection]
  110.         if self.complete:
  111.             self.encoder.connecter.connection_lost(self)
  112.  
  113.     def send_message(self, message):
  114.         self.connection.write(tobinary(len(message)) + message)
  115.  
  116.     def data_came_in(self, s):
  117.         while True:
  118.             if self.closed:
  119.                 return
  120.             i = self.next_len - self.buffer.tell()
  121.             if i > len(s):
  122.                 self.buffer.write(s)
  123.                 return
  124.             self.buffer.write(s[:i])
  125.             s = s[i:]
  126.             m = self.buffer.getvalue()
  127.             self.buffer.reset()
  128.             self.buffer.truncate()
  129.             try:
  130.                 x = self.next_func(m)
  131.             except:
  132.                 self.next_len, self.next_func = 1, self.read_dead
  133.                 raise
  134.             if x is None:
  135.                 self.close()
  136.                 return
  137.             self.next_len, self.next_func = x
  138.  
  139. class Encoder:
  140.     def __init__(self, connecter, raw_server, my_id, max_len,
  141.             schedulefunc, keepalive_delay, download_id, 
  142.             max_initiate = 40):
  143.         self.raw_server = raw_server
  144.         self.connecter = connecter
  145.         self.my_id = my_id
  146.         self.max_len = max_len
  147.         self.schedulefunc = schedulefunc
  148.         self.keepalive_delay = keepalive_delay
  149.         self.download_id = download_id
  150.         self.max_initiate = max_initiate
  151.         self.everinc = False
  152.         self.connections = {}
  153.         self.spares = []
  154.         schedulefunc(self.send_keepalives, keepalive_delay)
  155.  
  156.     def send_keepalives(self):
  157.         self.schedulefunc(self.send_keepalives, self.keepalive_delay)
  158.         for c in self.connections.values():
  159.             if c.complete:
  160.                 c.send_message('')
  161.  
  162.     def start_connection(self, dns, id):
  163.         if id:
  164.             if id == self.my_id:
  165.                 return
  166.             for v in self.connections.values():
  167.                 if v.id == id:
  168.                     return
  169.         if len(self.connections) >= self.max_initiate:
  170.             if len(self.spares) < self.max_initiate and dns not in self.spares:
  171.                 self.spares.append(dns)
  172.             return
  173.         try:
  174.             c = self.raw_server.start_connection(dns)
  175.             self.connections[c] = Connection(self, c, id, True)
  176.         except socketerror:
  177.             pass
  178.     
  179.     def _start_connection(self, dns, id):
  180.         def foo(self=self, dns=dns, id=id):
  181.             self.start_connection(dns, id)
  182.         
  183.         self.schedulefunc(foo, 0)
  184.         
  185.     def got_id(self, connection):
  186.         for v in self.connections.values():
  187.             if connection is not v and connection.id == v.id:
  188.                 connection.close()
  189.                 return
  190.         self.connecter.connection_made(connection)
  191.  
  192.     def ever_got_incoming(self):
  193.         return self.everinc
  194.  
  195.     def external_connection_made(self, connection):
  196.         self.connections[connection] = Connection(self, 
  197.             connection, None, False)
  198.  
  199.     def connection_flushed(self, connection):
  200.         c = self.connections[connection]
  201.         if c.complete:
  202.             self.connecter.connection_flushed(c)
  203.  
  204.     def connection_lost(self, connection):
  205.         self.connections[connection].sever()
  206.         while len(self.connections) < self.max_initiate and self.spares:
  207.             self.start_connection(self.spares.pop(), None)
  208.  
  209.     def data_came_in(self, connection, data):
  210.         self.connections[connection].data_came_in(data)
  211.  
  212. # everything below is for testing
  213.  
  214. class DummyConnecter:
  215.     def __init__(self):
  216.         self.log = []
  217.         self.close_next = False
  218.     
  219.     def connection_made(self, connection):
  220.         self.log.append(('made', connection))
  221.         
  222.     def connection_lost(self, connection):
  223.         self.log.append(('lost', connection))
  224.  
  225.     def connection_flushed(self, connection):
  226.         self.log.append(('flushed', connection))
  227.  
  228.     def got_message(self, connection, message):
  229.         self.log.append(('got', connection, message))
  230.         if self.close_next:
  231.             connection.close()
  232.  
  233. class DummyRawServer:
  234.     def __init__(self):
  235.         self.connects = []
  236.     
  237.     def start_connection(self, dns):
  238.         c = DummyRawConnection()
  239.         self.connects.append((dns, c))
  240.         return c
  241.  
  242. class DummyRawConnection:
  243.     def __init__(self):
  244.         self.closed = False
  245.         self.data = []
  246.         self.flushed = True
  247.  
  248.     def get_ip(self):
  249.         return 'fake.ip'
  250.  
  251.     def is_flushed(self):
  252.         return self.flushed
  253.  
  254.     def write(self, data):
  255.         assert not self.closed
  256.         self.data.append(data)
  257.         
  258.     def close(self):
  259.         assert not self.closed
  260.         self.closed = True
  261.  
  262.     def pop(self):
  263.         r = ''.join(self.data)
  264.         del self.data[:]
  265.         return r
  266.  
  267. def dummyschedule(a, b):
  268.     pass
  269.  
  270. def test_messages_in_and_out():
  271.     c = DummyConnecter()
  272.     rs = DummyRawServer()
  273.     e = Encoder(c, rs, 'a' * 20, 500, dummyschedule, 30, 'd' * 20)
  274.     c1 = DummyRawConnection()
  275.     e.external_connection_made(c1)
  276.     assert c1.pop() == ''
  277.     assert c.log == []
  278.     assert rs.connects == []
  279.     assert not c1.closed
  280.  
  281.     e.data_came_in(c1, chr(len(protocol_name)) + protocol_name + \
  282.         chr(0) * 8 + 'd' * 20)
  283.     assert c1.pop() == chr(len(protocol_name)) + protocol_name + \
  284.         chr(0) * 8 + 'd' * 20 + 'a' * 20
  285.     assert c.log == []
  286.     assert rs.connects == []
  287.     assert not c1.closed
  288.  
  289.     e.data_came_in(c1, 'b' * 20)
  290.     assert c1.pop() == ''
  291.     assert len(c.log) == 1
  292.     assert c.log[0][0] == 'made'
  293.     ch = c.log[0][1]
  294.     del c.log[:]
  295.     assert rs.connects == []
  296.     assert not c1.closed
  297.     assert ch.get_ip() == 'fake.ip'
  298.     
  299.     ch.send_message('abc')
  300.     assert c1.pop() == chr(0) * 3 + chr(3) + 'abc'
  301.     assert c.log == []
  302.     assert rs.connects == []
  303.     assert not c1.closed
  304.     
  305.     e.data_came_in(c1, chr(0) * 3 + chr(3) + 'def')
  306.     assert c1.pop() == ''
  307.     assert c.log == [('got', ch, 'def')]
  308.     del c.log[:]
  309.     assert rs.connects == []
  310.     assert not c1.closed
  311.  
  312. def test_flushed():
  313.     c = DummyConnecter()
  314.     rs = DummyRawServer()
  315.     e = Encoder(c, rs, 'a' * 20, 500, dummyschedule, 30, 'd' * 20)
  316.     c1 = DummyRawConnection()
  317.     e.external_connection_made(c1)
  318.     assert c1.pop() == ''
  319.     assert c.log == []
  320.     assert rs.connects == []
  321.     assert not c1.closed
  322.  
  323.     e.data_came_in(c1, chr(len(protocol_name)) + protocol_name + \
  324.         chr(0) * 8 + 'd' * 20)
  325.     assert c1.pop() == chr(len(protocol_name)) + protocol_name + \
  326.         chr(0) * 8 + 'd' * 20 + 'a' * 20
  327.     assert c1.pop() == ''
  328.     assert c.log == []
  329.     assert rs.connects == []
  330.     assert not c1.closed
  331.     
  332.     e.connection_flushed(c1)
  333.     assert c1.pop() == ''
  334.     assert c.log == []
  335.     assert rs.connects == []
  336.     assert not c1.closed
  337.  
  338.     e.data_came_in(c1, 'b' * 20)
  339.     assert c1.pop() == ''
  340.     assert len(c.log) == 1
  341.     assert c.log[0][0] == 'made'
  342.     ch = c.log[0][1]
  343.     del c.log[:]
  344.     assert rs.connects == []
  345.     assert not c1.closed
  346.     assert ch.is_flushed()
  347.     
  348.     e.connection_flushed(c1)
  349.     assert c1.pop() == ''
  350.     assert c.log == [('flushed', ch)]
  351.     assert rs.connects == []
  352.     assert not c1.closed
  353.     
  354.     c1.flushed = False
  355.     assert not ch.is_flushed()
  356.     
  357. def test_wrong_header_length():
  358.     c = DummyConnecter()
  359.     rs = DummyRawServer()
  360.     e = Encoder(c, rs, 'a' * 20, 500, dummyschedule, 30, 'd' * 20)
  361.     c1 = DummyRawConnection()
  362.     e.external_connection_made(c1)
  363.     assert c1.pop() == ''
  364.     assert c.log == []
  365.     assert rs.connects == []
  366.     assert not c1.closed
  367.  
  368.     e.data_came_in(c1, chr(5) * 30)
  369.     assert c.log == []
  370.     assert c1.closed
  371.  
  372. def test_wrong_header():
  373.     c = DummyConnecter()
  374.     rs = DummyRawServer()
  375.     e = Encoder(c, rs, 'a' * 20, 500, dummyschedule, 30, 'd' * 20)
  376.     c1 = DummyRawConnection()
  377.     e.external_connection_made(c1)
  378.     assert c1.pop() == ''
  379.     assert c.log == []
  380.     assert rs.connects == []
  381.     assert not c1.closed
  382.  
  383.     e.data_came_in(c1, chr(len(protocol_name)) + 'a' * len(protocol_name))
  384.     assert c.log == []
  385.     assert c1.closed
  386.     
  387. def test_wrong_download_id():
  388.     c = DummyConnecter()
  389.     rs = DummyRawServer()
  390.     e = Encoder(c, rs, 'a' * 20, 500, dummyschedule, 30, 'd' * 20)
  391.     c1 = DummyRawConnection()
  392.     e.external_connection_made(c1)
  393.     assert c1.pop() == ''
  394.     assert c.log == []
  395.     assert rs.connects == []
  396.     assert not c1.closed
  397.  
  398.     e.data_came_in(c1, chr(len(protocol_name)) + protocol_name + 
  399.         chr(0) * 8 + 'e' * 20)
  400.     assert c1.pop() == ''
  401.     assert c.log == []
  402.     assert c1.closed
  403.  
  404. def test_wrong_other_id():
  405.     c = DummyConnecter()
  406.     rs = DummyRawServer()
  407.     e = Encoder(c, rs, 'a' * 20, 500, dummyschedule, 30, 'd' * 20)
  408.     e.start_connection('dns', 'o' * 20)
  409.     assert c.log == []
  410.     assert len(rs.connects) == 1
  411.     assert rs.connects[0][0] == 'dns'
  412.     c1 = rs.connects[0][1]
  413.     del rs.connects[:]
  414.     assert c1.pop() == chr(len(protocol_name)) + protocol_name + \
  415.         chr(0) * 8 + 'd' * 20 + 'a' * 20
  416.     assert not c1.closed
  417.  
  418.     e.data_came_in(c1, chr(len(protocol_name)) + protocol_name + 
  419.         chr(0) * 8 + 'd' * 20 + 'b' * 20)
  420.     assert c.log == []
  421.     assert c1.closed
  422.  
  423. def test_over_max_len():
  424.     c = DummyConnecter()
  425.     rs = DummyRawServer()
  426.     e = Encoder(c, rs, 'a' * 20, 500, dummyschedule, 30, 'd' * 20)
  427.     c1 = DummyRawConnection()
  428.     e.external_connection_made(c1)
  429.     assert c1.pop() == ''
  430.     assert c.log == []
  431.     assert rs.connects == []
  432.     assert not c1.closed
  433.  
  434.     e.data_came_in(c1, chr(len(protocol_name)) + protocol_name + 
  435.         chr(0) * 8 + 'd' * 20 + 'o' * 20)
  436.     assert c1.pop() == chr(len(protocol_name)) + protocol_name + \
  437.         chr(0) * 8 + 'd' * 20 + 'a' * 20
  438.     assert len(c.log) == 1 and c.log[0][0] == 'made'
  439.     ch = c.log[0][1]
  440.     del c.log[:]
  441.     assert not c1.closed
  442.  
  443.     e.data_came_in(c1, chr(1) + chr(0) * 3)
  444.     assert c.log == [('lost', ch)]
  445.     assert c1.closed
  446.  
  447. def test_keepalive():
  448.     s = []
  449.     def sched(interval, thing, s = s):
  450.         s.append((interval, thing))
  451.     c = DummyConnecter()
  452.     rs = DummyRawServer()
  453.     e = Encoder(c, rs, 'a' * 20, 500, sched, 30, 'd' * 20)
  454.     assert len(s) == 1
  455.     assert s[0][1] == 30
  456.     kfunc = s[0][0]
  457.     del s[:]
  458.     c1 = DummyRawConnection()
  459.     e.external_connection_made(c1)
  460.     assert c1.pop() == ''
  461.     assert c.log == []
  462.     assert not c1.closed
  463.  
  464.     kfunc()
  465.     assert c1.pop() == ''
  466.     assert c.log == []
  467.     assert not c1.closed
  468.     assert s == [(kfunc, 30)]
  469.     del s[:]
  470.  
  471.     e.data_came_in(c1, chr(len(protocol_name)) + protocol_name + 
  472.         chr(0) * 8 + 'd' * 20 + 'o' * 20)
  473.     assert len(c.log) == 1 and c.log[0][0] == 'made'
  474.     del c.log[:]
  475.     assert c1.pop() == chr(len(protocol_name)) + protocol_name + \
  476.         chr(0) * 8 + 'd' * 20 + 'a' * 20
  477.     assert not c1.closed
  478.  
  479.     kfunc()
  480.     assert c1.pop() == chr(0) * 4
  481.     assert c.log == []
  482.     assert not c1.closed
  483.  
  484. def test_swallow_keepalive():
  485.     c = DummyConnecter()
  486.     rs = DummyRawServer()
  487.     e = Encoder(c, rs, 'a' * 20, 500, dummyschedule, 30, 'd' * 20)
  488.     c1 = DummyRawConnection()
  489.     e.external_connection_made(c1)
  490.     assert c1.pop() == ''
  491.     assert c.log == []
  492.     assert rs.connects == []
  493.     assert not c1.closed
  494.  
  495.     e.data_came_in(c1, chr(len(protocol_name)) + protocol_name + 
  496.         chr(0) * 8 + 'd' * 20 + 'o' * 20)
  497.     assert c1.pop() == chr(len(protocol_name)) + protocol_name + \
  498.         chr(0) * 8 + 'd' * 20 + 'a' * 20
  499.     assert len(c.log) == 1 and c.log[0][0] == 'made'
  500.     del c.log[:]
  501.     assert not c1.closed
  502.  
  503.     e.data_came_in(c1, chr(0) * 4)
  504.     assert c.log == []
  505.     assert not c1.closed
  506.  
  507. def test_local_close():
  508.     c = DummyConnecter()
  509.     rs = DummyRawServer()
  510.     e = Encoder(c, rs, 'a' * 20, 500, dummyschedule, 30, 'd' * 20)
  511.     c1 = DummyRawConnection()
  512.     e.external_connection_made(c1)
  513.     assert c1.pop() == ''
  514.     assert c.log == []
  515.     assert rs.connects == []
  516.     assert not c1.closed
  517.  
  518.     e.data_came_in(c1, chr(len(protocol_name)) + protocol_name + 
  519.         chr(0) * 8 + 'd' * 20 + 'o' * 20)
  520.     assert c1.pop() == chr(len(protocol_name)) + protocol_name + \
  521.         chr(0) * 8 + 'd' * 20 + 'a' * 20
  522.     assert len(c.log) == 1 and c.log[0][0] == 'made'
  523.     ch = c.log[0][1]
  524.     del c.log[:]
  525.     assert not c1.closed
  526.  
  527.     ch.close()
  528.     assert c.log == [('lost', ch)]
  529.     del c.log[:]
  530.     assert c1.closed
  531.  
  532. def test_local_close_in_message_receive():
  533.     c = DummyConnecter()
  534.     rs = DummyRawServer()
  535.     e = Encoder(c, rs, 'a' * 20, 500, dummyschedule, 30, 'd' * 20)
  536.     c1 = DummyRawConnection()
  537.     e.external_connection_made(c1)
  538.     assert c1.pop() == ''
  539.     assert c.log == []
  540.     assert rs.connects == []
  541.     assert not c1.closed
  542.  
  543.     e.data_came_in(c1, chr(len(protocol_name)) + protocol_name + 
  544.         chr(0) * 8 + 'd' * 20 + 'o' * 20)
  545.     assert c1.pop() == chr(len(protocol_name)) + protocol_name + \
  546.         chr(0) * 8 + 'd' * 20 + 'a' * 20
  547.     assert len(c.log) == 1 and c.log[0][0] == 'made'
  548.     ch = c.log[0][1]
  549.     del c.log[:]
  550.     assert not c1.closed
  551.  
  552.     c.close_next = True
  553.     e.data_came_in(c1, chr(0) * 3 + chr(4) + 'abcd')
  554.     assert c.log == [('got', ch, 'abcd'), ('lost', ch)]
  555.     assert c1.closed
  556.  
  557. def test_remote_close():
  558.     c = DummyConnecter()
  559.     rs = DummyRawServer()
  560.     e = Encoder(c, rs, 'a' * 20, 500, dummyschedule, 30, 'd' * 20)
  561.     c1 = DummyRawConnection()
  562.     e.external_connection_made(c1)
  563.     assert c1.pop() == ''
  564.     assert c.log == []
  565.     assert rs.connects == []
  566.     assert not c1.closed
  567.  
  568.     e.data_came_in(c1, chr(len(protocol_name)) + protocol_name + 
  569.         chr(0) * 8 + 'd' * 20 + 'o' * 20)
  570.     assert c1.pop() == chr(len(protocol_name)) + protocol_name + \
  571.         chr(0) * 8 + 'd' * 20 + 'a' * 20
  572.     assert len(c.log) == 1 and c.log[0][0] == 'made'
  573.     ch = c.log[0][1]
  574.     del c.log[:]
  575.     assert not c1.closed
  576.  
  577.     e.connection_lost(c1)
  578.     assert c.log == [('lost', ch)]
  579.     assert not c1.closed
  580.  
  581. def test_partial_data_in():
  582.     c = DummyConnecter()
  583.     rs = DummyRawServer()
  584.     e = Encoder(c, rs, 'a' * 20, 500, dummyschedule, 30, 'd' * 20)
  585.     c1 = DummyRawConnection()
  586.     e.external_connection_made(c1)
  587.     assert c1.pop() == ''
  588.     assert c.log == []
  589.     assert rs.connects == []
  590.     assert not c1.closed
  591.  
  592.     e.data_came_in(c1, chr(len(protocol_name)) + protocol_name + 
  593.         chr(0) * 4)
  594.     e.data_came_in(c1, chr(0) * 4 + 'd' * 20 + 'c' * 10)
  595.     e.data_came_in(c1, 'c' * 10)
  596.     assert c1.pop() == chr(len(protocol_name)) + protocol_name + \
  597.         chr(0) * 8 + 'd' * 20 + 'a' * 20
  598.     assert len(c.log) == 1 and c.log[0][0] == 'made'
  599.     del c.log[:]
  600.     assert not c1.closed
  601.     
  602. def test_ignore_connect_of_extant():
  603.     c = DummyConnecter()
  604.     rs = DummyRawServer()
  605.     e = Encoder(c, rs, 'a' * 20, 500, dummyschedule, 30, 'd' * 20)
  606.     c1 = DummyRawConnection()
  607.     e.external_connection_made(c1)
  608.     assert c1.pop() == ''
  609.     assert c.log == []
  610.     assert rs.connects == []
  611.     assert not c1.closed
  612.  
  613.     e.data_came_in(c1, chr(len(protocol_name)) + protocol_name + 
  614.         chr(0) * 8 + 'd' * 20 + 'o' * 20)
  615.     assert c1.pop() == chr(len(protocol_name)) + protocol_name + \
  616.         chr(0) * 8 + 'd' * 20 + 'a' * 20
  617.     assert len(c.log) == 1 and c.log[0][0] == 'made'
  618.     del c.log[:]
  619.     assert not c1.closed
  620.  
  621.     e.start_connection('dns', 'o' * 20)
  622.     assert c.log == []
  623.     assert rs.connects == []
  624.     assert not c1.closed
  625.  
  626. def test_ignore_connect_to_self():
  627.     c = DummyConnecter()
  628.     rs = DummyRawServer()
  629.     e = Encoder(c, rs, 'a' * 20, 500, dummyschedule, 30, 'd' * 20)
  630.     c1 = DummyRawConnection()
  631.  
  632.     e.start_connection('dns', 'a' * 20)
  633.     assert c.log == []
  634.     assert rs.connects == []
  635.     assert not c1.closed
  636.  
  637. def test_conversion():
  638.     assert toint(tobinary(50000)) == 50000
  639.  
  640.